ClojureDocs

Nav

Namespaces

->>

clojure.core

Available since 1.1 (source)
  • (->> x & forms)
Threads the expr through the forms. Inserts x as the
last item in the first form, making a list of it if it is not a
list already. If there are more forms, inserts the first form as the
last item in second form, etc.
11 Examples
;; An example of using the "thread-last" macro to get
;; the sum of the first 10 even squares.
user=> (->> (range)
            (map #(* % %))
            (filter even?)
            (take 10)
            (reduce +))
1140

;; This expands to:
user=> (reduce +
               (take 10
                     (filter even?
                             (map #(* % %)
                                  (range)))))
1140
user=> (def c 5)
user=> (->> c (+ 3) (/ 2) (- 1))                          
3/4

;; and if you are curious why
user=> (use 'clojure.walk)
user=> (macroexpand-all '(->> c (+ 3) (/ 2) (- 1)))
(- 1 (/ 2 (+ 3 c)))

;; let's compare thread first (->) and thread last ( ->> )
user=> (macroexpand '(-> 0 (+ 1) (+ 2) (+ 3)))
(+ (+ (+ 0 1) 2) 3)
user=> (macroexpand '(->> 0 (+ 1) (+ 2) (+ 3)))
(+ 3 (+ 2 (+ 1 0)))
;; ->> and -> by simple string concatenation

;; Effectively (str " jmd" "hello")
user=> (->> "hello" (str " jmd"))
" jmdhello"

;; Effectively (str "hello" " jmd")
user=> (-> "hello" (str " jmd"))
=> "hello jmd"
;; It is OK to omit the parentheses if a function takes only one argument
(->> [1 2 [3 4] 5]
     flatten  ; no parenthesis
     (map inc))
=> (2 3 4 5 6)
     
;; It's OK to include anonymous function in the thread, but don't forget
;; to put in an extra pair of parentheses to call the function
(->> [1 2 3 4 5]
     ((fn [coll] (map inc coll))) ; double parentheses
     (apply +))                          
=> 20

;; the short hand form of the anonymous function works the same
(->> [1 2 3 4 5]
     (#(map inc %)) ; double parentheses
     (apply +))  

;; avoid function
(->> [1 2 3 4 5]
     (map inc) ; single parentheses
     (apply +))  
;; For large threads you can use commas (interpreted as whitespaces) 
;; to visualize where the items are going to be inserted.

;; Takes the first 5 even numbers
user=> (->> (range)
            (filter even?)
            (take 5))
=> (0 2 4 6 8)

;; with two commas (you can use one if you prefer)
user=> (->> (range)
            (filter even? ,,)
            (take 5 ,,))
=> (0 2 4 6 8)

;; For instance:
;; (filter even? ,,)
;; means
;; (filter even? (range))
;;practical example

(def entries [{:month 1 :val 12}
              {:month 2 :val 3}
              {:month 3 :val 32}
              {:month 4 :val 18}
              {:month 5 :val 32}
              {:month 6 :val 62}
              {:month 7 :val 12}
              {:month 8 :val 142}
              {:month 9 :val 52}
              {:month 10 :val 18}
              {:month 11 :val 23}
              {:month 12 :val 56}])
(defn get-result
  [coll m]
  (->> coll
       (take-while
        #(<= (:month %) m))))

(defn get-total
  [coll m]
  (->>
   (get-result coll m)
   (map #(:val %))
   (reduce +)))

(get-total entries 3)
(defn new-map
  [coll]
  (->>
   coll
   (map
    (fn [[k v]]
      [k (inc v)]))
   (into {})))

(new-map {:a 1 :b 2 :c 3})
(defn f [front a1 a2 end] (str front "-" a1 "-" a2  "-" end))
(println (f 1 2 3 4))
;; => 1-2-3-4
(println (-> 1 (f 2 3 4)))
;; => 1-2-3-4
(println (->> 1 (f 2 3 4)))
;; => 2-3-4-1
(->> (str "A") (str "B") (str   "C"))
;; => "CBA"
(-> (str "A") (str "B") (str   "C"))
;; => "ABC"
See Also

Threads the expr through the forms. Inserts x as the second item in the first form, making a list ...

Added by 0x89

When expr is not nil, threads it into the first form (via ->>), and when that result is not nil, t...

Added by jw-00000

Takes a set of functions and returns a fn that is the composition of those fns. The returned fn t...

Added by phreed

Takes an expression and a set of test/form pairs. Threads expr (via ->>) through each form for whi...

Added by boxxxie

Takes an expression and a set of test/form pairs. Threads expr (via ->) through each form for whic...

Added by boxxxie

Binds name to expr, evaluates the first form in the lexical context of that binding, then binds na...

Added by boxxxie
5 Notes
    By , created 14.7 years ago, updated 14.7 years ago

    I'm getting: Exception in thread "main" java.lang.Exception: Unable to resolve symbol: -&gt;&gt; in this context (11.clj:25)

    It's also extremely hard to Google this method. It'd be nice if there was a non-symbol name for this that one could search for.

    Update

    The name of this operator is called a thrush.

    By , created 14.7 years ago

    See also -> which is similar but threads the first expr as the second argument of the forms.

    By , created 14.7 years ago

    My error was due to using an old version of Clojure. I was using 1.0.0.

    By , created 10.9 years ago

    There is something I don't get : in the case "form" is a seq, why should we write ... (with-meta `(~(first form) ~@(next form) ~x) (meta form))

    and not ... (with-meta `(~@form ~x) (meta form))

    as items order in "form" is not changed ?

    By , created 9.5 years ago

    "See also -> which is similar but threads the first expr as the second argument of the forms."

    This is incorrect, it is not the second ARGUMENT, but the second ITEM.